using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;


namespace project1
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {

        #region member vars

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        private const float fireRate = 1.6f;
        private float firing = fireRate;

        //private AsteroidField asteroidField;
        private Trumpet trumpet;

        private Camera camera;

        private KeyboardState lastKeyBoardState;

        /// <summary>
        /// A reference to the audio engine we use
        /// </summary>
       // AudioEngine audioEngine;

        /// <summary>
        /// The loaded audio wave bank
        /// </summary>
      ///  WaveBank waveBank;

        /// <summary>
        /// The loaded audio sound bank
        /// </summary>
      //  SoundBank soundBank;

        private SpriteFont scoreFont;

        private int score = 0;




        #endregion

        public Camera Camera { get { return camera; } }


        //public SoundBank SoundBank { get { return soundBank; } }

        public int Score { get { return score; } set { score = value; } }

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            //asteroidField = new AsteroidField(this);
            trumpet = new Trumpet(this);
            //trumpet = new trumpet(this);
            camera = new Camera(graphics);
        }






        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            camera.Initialize();
            camera.Eye = new Vector3(1000, 1000, 1000);
            lastKeyBoardState = Keyboard.GetState();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            trumpet.LoadContent(Content);
            //trumpet.LoadContent(Content);
            //asteroidField.LoadContent(Content);

            //audio
            //audioEngine = new AudioEngine("Content\\trumpetAudio.xgs");
            //waveBank = new WaveBank(audioEngine, "Content\\Wave Bank.xwb");
            //soundBank = new SoundBank(audioEngine, "Content\\Sound Bank.xsb");

            scoreFont = Content.Load<SpriteFont>("scorefont");

        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // TODO: Add your update logic here
            KeyboardState keyboardState = Keyboard.GetState();

            if (keyboardState.IsKeyDown(Keys.D1) && lastKeyBoardState.IsKeyUp(Keys.D1))
            {
                if (trumpet.Valve1Pressed)
                    trumpet.Valve1Pressed = false;
                else
                    trumpet.Valve1Pressed = true;
            }

            if (keyboardState.IsKeyDown(Keys.D2) && lastKeyBoardState.IsKeyUp(Keys.D2))
            {
                if (trumpet.Valve2Pressed)
                    trumpet.Valve2Pressed = false;
                else
                    trumpet.Valve2Pressed = true;
            }

            if (keyboardState.IsKeyDown(Keys.D3) && lastKeyBoardState.IsKeyUp(Keys.D3))
            {
                if (trumpet.Valve3Pressed)
                    trumpet.Valve3Pressed = false;
                else
                    trumpet.Valve3Pressed = true;
            }

            if (keyboardState.IsKeyDown(Keys.LeftShift) && lastKeyBoardState.IsKeyUp(Keys.LeftShift))
            {
                if (trumpet.Slide1Pressed)
                    trumpet.Slide1Pressed = false;
                else
                    trumpet.Slide1Pressed = true;
            }

            if (keyboardState.IsKeyDown(Keys.E))
            {
                trumpet.Thrust = 1;
            }
            else
            {
                trumpet.Thrust = 0;
            }

            if (keyboardState.IsKeyDown(Keys.Left))
            {
                trumpet.TurnRate = 1;
                trumpet.BankingRate = 1;
            }

            else if (keyboardState.IsKeyDown(Keys.Right))
            {
                trumpet.TurnRate = -1;
                trumpet.BankingRate = -1;
            }
            else
            {
                trumpet.TurnRate = 0;
                trumpet.BankingRate = 0;
            }

            if (keyboardState.IsKeyDown(Keys.Up))
            {
                trumpet.ElevationRate = 1f;
            }

            else if (keyboardState.IsKeyDown(Keys.Down))
            {
                trumpet.ElevationRate = -1;
            }

            else
            {
                trumpet.ElevationRate = 0;
            }

            if (keyboardState.IsKeyDown(Keys.X) && lastKeyBoardState.IsKeyUp(Keys.X))
            {
                trumpet.Deployed = !trumpet.Deployed;
            }

            if (keyboardState.IsKeyDown(Keys.Space) && lastKeyBoardState.IsKeyUp(Keys.Space))
            {
                trumpet.FireLaser();
            }
            else if ((keyboardState.IsKeyDown(Keys.Space)))
            {
                if (firing > 0)
                {
                    firing -= (float)gameTime.ElapsedGameTime.TotalSeconds;
                }
                else
                {
                    trumpet.FireLaser();
                    firing = fireRate;
                }


            }


            lastKeyBoardState = keyboardState;

            //asteroidField.Update(gameTime);
            trumpet.Update(gameTime);
            //trumpet.Update(gameTime);

            camera.UseChaseCamera = false;
            camera.DesiredEye = Vector3.Transform(new Vector3(0, 318, -1677), trumpet.Transform);
            camera.DesiredUp = (trumpet.Transform.Up);
            camera.Center = trumpet.Position;
            camera.Update(gameTime);



            ///checks the lasers against the asteroids
            for (LinkedListNode<LaserFire.LaserBlast> blastNode = trumpet.LaserFire.LaserBlasts.First; blastNode != null; )
            {
                LinkedListNode<LaserFire.LaserBlast> nextNode = blastNode.Next;
                LaserFire.LaserBlast blast = blastNode.Value;

                /*
                if (asteroidField.TestLaserForCollision(blast.position))
                {
                    trumpet.LaserFire.LaserBlasts.Remove(blast);
                }
                 * */

                blastNode = nextNode;
            }



            Matrix[] transforms = new Matrix[trumpet.Model.Bones.Count];
            trumpet.Model.CopyAbsoluteBoneTransformsTo(transforms);
            Matrix trumpetTransform = trumpet.Transform;


            foreach (ModelMesh mesh in trumpet.Model.Meshes)
            {
                BoundingSphere bs = mesh.BoundingSphere;
                bs = bs.Transform(transforms[mesh.ParentBone.Index] * trumpetTransform);
                /*
                if (asteroidField.TestSphereForCollision(bs))
                {
                    this.SoundBank.PlayCue("explosion3");
                    ResetGame();
                    //this.Exit();
                }
                 */
            }





            //update audioEngine
            //audioEngine.Update();


            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);

            // TODO: Add your drawing code here
            //asteroidField.Draw(graphics, gameTime);
            trumpet.Draw(graphics, gameTime);
            //trumpet.Draw(graphics, gameTime);

            spriteBatch.Begin();
            spriteBatch.DrawString(scoreFont, score.ToString(), new Vector2(10, 10), Color.White);
            spriteBatch.End();
            GraphicsDevice.DepthStencilState = DepthStencilState.Default;

            base.Draw(gameTime);
        }

        public void ResetGame()
        {
            score = 0;
           // asteroidField.ClearAsteroids();
            //asteroidField.GenAsteroids();

            trumpet = new Trumpet(this);

            Initialize();
        }

    }
}
